home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
Source.bin
/
Firework.java
< prev
next >
Wrap
Text File
|
1998-10-08
|
13KB
|
420 lines
package symantec.itools.multimedia;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Dimension;
import java.net.URL;
import java.util.Random;
import symantec.itools.lang.OS;
// 01/29/97 TWB Integrated changes from Windows
// 02/02/97 RKM Fixed bug in unfreezeRockets, where freezing twice would not resume
// 07/15/97 CAR marked fields transient as needed
// 10/01/97 LAB Removed unnecessary clipRect calls. Now gets the graphics context each time
// the component is resized (Addresses Mac Bug #7832).
/**
* Firework component. Creates an animated fireworks image.
* @version 1.0, Nov 26, 1996
* @author Symantec
*/
public class Firework
extends Canvas
implements Runnable
{
/**
* Speed at which animation occurs. Delay time = 100 / AnimationSpeed.
* Default value 10.
*/
public int AnimationSpeed = 10;
/**
* Chance of different rocket style. Rocket sytle changes if Math.random() * 100 < RocketStyleVariability.
* Default Value 10.
*/
public int RocketStyleVariability = 10;
/**
* Maximum number of rockets.
*/
public int MaxRocketNumber = 9;
/**
* Controls "energy" of firwork explosion. Default value 850.
*/
public int MaxRocketExplosionEnergy = 850;
/**
* Controls the density of the firework burst. Larger numbers give higher density.
* Default value 90.
*/
public int MaxRocketPatchNumber = 90;
/**
* Controls the radius of the firework burst. Larger numbers give larger radius.
* Default value 68.
*/
public int MaxRocketPatchLength = 68;
/**
* Controls gravity of the firework simulation.
* Default value 400.
*/
public int Gravity = 400;
transient private Rocket rocket[];
transient private boolean rocketsCreated = false;
transient private Thread launcher = null;
transient private boolean suspend = false;
/**
* Construct the defalut firework.
*
*/
public Firework() {
super();
}
/**
* Tells this component that it has been added to a container.
* This is a standard Java AWT method which gets called by the AWT when
* this component is added to a container. Typically, it is used to
* create this component's peer.
*
* It has been overridden here to start the launcher thread.
*
* @see #removeNotify
*/
public void addNotify() {
super.addNotify();
launcher = new Thread(this);
launcher.start();
}
/**
* Tells this component that it is being removed from a container.
* This is a standard Java AWT method which gets called by the AWT when
* this component is removed from a container. Typically, it is used to
* destroy the peers of this component and all its subcomponents.
*
* It has been overridden here to stop the launcher thread.
*
* @see #addNotify
*/
public synchronized void removeNotify() {
if (launcher != null) {
launcher.stop();
launcher = null;
}
super.removeNotify();
}
/**
* Makes this component visible.
* This is a standard Java AWT method which gets called to show this
* component. If this component was invisible due to a previous hide()
* call it make this component visible again.
*
* @see #hide
*/
public synchronized void show() {
super.show();
if (isVisible()) {
if (launcher != null)
launcher.resume();
}
}
/**
* Makes this component invisible.
* This is a standard Java AWT method which gets called to hide
* this component. A hidden component cannot be seen by the user nor
* does it take up space in its container, but it does continue to
* exist.
*
* @see #show
*/
public synchronized void hide() {
super.hide();
if (!isVisible()) {
if (launcher != null)
suspend = true;
}
}
void createRockets() {
rocketsCreated = true;
Rocket tempRocket[] = new Rocket[MaxRocketNumber];
Dimension dim = size();
for (int i = 0; i < MaxRocketNumber; i++)
tempRocket[i] = new Rocket(dim.width, dim.height, Gravity);
rocket = tempRocket;
}
/**
* Moves and/or resizes this component.
* This is a standard Java AWT method which gets called to move and/or
* resize this component. Components that are in containers with layout
* managers should not call this method, but rely on the layout manager
* instead.
*
* @param x horizontal position in the parent's coordinate space
* @param y vertical position in the parent's coordinate space
* @param width the new width
* @param height the new height
*/
public synchronized void reshape(int x, int y, int width, int height) {
super.reshape(x, y, width, height);
rocketsCreated = false;
}
/**
* Firework thread body. This method is called by the Java virtual
* machine is response to the program's call to the start method of
* this thread.
*/
public void run() {
int i,
e = (int)(Math.random() * MaxRocketExplosionEnergy * 3 / 4) +
MaxRocketExplosionEnergy / 4 + 1,
p = (int)(Math.random() * MaxRocketPatchNumber * 3 / 4) +
MaxRocketPatchNumber / 4 + 1,
l = (int)(Math.random() * MaxRocketPatchLength * 3 / 4) +
MaxRocketPatchLength / 4 + 1;
long s = (long)(Math.random() * 10000);
boolean sleep;
Graphics g = null;
while (true) {
if (g == null)
g = getGraphics();
if (suspend) {
suspend = false;
launcher.suspend();
}
if (!rocketsCreated)
{
g = getGraphics();
createRockets();
}
if (rocketsCreated && g != null) {
Dimension dim = size();
try {
Thread.sleep(100 / AnimationSpeed);
} catch(InterruptedException x) {
}
sleep = true;
for (i = 0; i < MaxRocketNumber; i++)
sleep = sleep && rocket[i].sleep;
if (sleep && Math.random() * 100 < RocketStyleVariability) {
e = (int)(Math.random() * MaxRocketExplosionEnergy * 3 / 4) +
MaxRocketExplosionEnergy / 4 + 1;
p = (int)(Math.random() * MaxRocketPatchNumber * 3 / 4) +
MaxRocketPatchNumber / 4 + 1;
l = (int)(Math.random() * MaxRocketPatchLength * 3 / 4) +
MaxRocketPatchLength / 4 + 1;
s = (long)(Math.random() * 10000);
}
for (i = 0; i < MaxRocketNumber; ++i) {
Rocket r = rocket[i];
if (r.sleep && Math.random() * MaxRocketNumber * l < 1) {
r.init(e, p, l, s);
r.start();
}
if (rocketsCreated)
r.show(g);
}
}
}
}
/**
* Suspend the firework animation.
*/
public void freezeRockets() {
suspend = true;
}
/**
* Resume the firework animation.
*/
public void unfreezeRockets() {
//Set suspend to false, in case freezeRockets was called after it was suspended
suspend = false;
launcher.resume();
}
/**
* Paints a black background for this firework.
* This is a standard Java AWT method which typically gets called
* by the AWT to handle painting this component. It paints this component
* using the given graphics context. The graphics context clipping region
* is set to the bounding rectangle of this component and its <0,0>
* coordinate is this component's top-left corner.
*
* @param g the graphics context used for painting
* @see java.awt.Component#repaint
* @see java.awt.Component#update
*/
public void paint(Graphics g) {
Dimension dim = size();
g.setColor(Color.black);
g.fillRect(0, 0, dim.width + 1, dim.height + 1);
}
}
class Rocket {
public boolean sleep = true;
private int energy,patch,length,
mx,my,
gravity,
ox,oy,
vx[],vy[],
x,y,
red,blue,green,
t;
private Random random;
public Rocket(int a, int b, int g) {
mx = a;
my = b;
gravity = g;
}
public void init(int e, int p, int l, long seed) {
int i;
energy = e;
patch = p;
length = l;
random = new Random(seed);
vx = new int[patch];
vy = new int[patch];
if (!System.getProperty("os.name").equals("Windows 95")) {
red = (int)(random.nextDouble() * 128) + 128;
blue = (int)(random.nextDouble() * 128) + 128;
green = (int)(random.nextDouble() * 128) + 128;
}
else {
int add = 0;
double d = 0.0;
d = random.nextDouble();
if (d >= 0.0 && d <= .2) add = 0;
if (d > .2 && d <= .4) add = 32;
if (d > .4 && d <= .6) add = 64;
if (d > .6 && d <= .8) add = 96;
if (d > .8 && d <= 1.0) add = 128;
red = add + 128;
d = random.nextDouble();
if (d >= 0.0 && d <= .2) add = 0;
if (d > .2 && d <= .4) add = 32;
if (d > .4 && d <= .6) add = 64;
if (d > .6 && d <= .8) add = 96;
if (d > .8 && d <= 1.0) add = 128;
blue = add + 128;
d = random.nextDouble();
if (d >= 0.0 && d <= .2) add = 0;
if (d > .2 && d <= .4) add = 32;
if (d > .4 && d <= .6) add = 64;
if (d > .6 && d <= .8) add = 96;
if (d > .8 && d <= 1.0) add = 128;
green = add + 128;
}
ox = (int)(Math.random()*mx/2)+mx/4;
oy = (int)(Math.random()*my/2)+my/4;
for(i = 0; i < patch; ++i) {
vx[i] = (int)(Math.random() * energy) - energy / 2;
vy[i] = (int)(Math.random() * energy * 7 / 8) - energy / 8;
}
}
public void start() {
t = 0;
sleep = false;
}
public void show(Graphics g) {
if (!sleep) {
if (t < length) {
int i, cr, cg, cb;
double s;
Color color;
if (!System.getProperty("os.name").equals("Windows 95")) {
cr = (int)(random.nextDouble() * 64) - 32 + red;
cg = (int)(random.nextDouble() * 64) - 32 + green;
cb = (int)(random.nextDouble() * 64) - 32 + blue;
}
else {
cr = (random.nextDouble() < 0.50 ? -32 : 32) + red;
cg = (random.nextDouble() < 0.50 ? -32 : 32) + green;
cb = (random.nextDouble() < 0.50 ? -32 : 32) + blue;
}
if (cr >= 0 && cr <= 256)
red = cr;
if (cg >= 0 && cg <= 256)
green = cg;
if (cb >= 0 && cb <= 256)
blue = cb;
int _red = red == 256 ? 255 : red;
int _green = green == 256 ? 255 : green;
int _blue = blue == 256 ? 255 : blue;
color = new Color(_red, _green, _blue);
g.setColor(color);
for (i = 0; i < patch; ++i) {
s = (double)t / 100;
x = (int)(vx[i] * s);
y = (int)(vy[i] * s - gravity * s * s);
g.drawLine(ox + x, oy - y, ox + x, oy - y);
}
g.setColor(Color.black);
for (i = 0; i < patch; ++i) {
if (t >= length / 2) {
for (int j = 0; j < 2; ++j)
{
s = (double)((t - length / 2) * 2 + j) / 100;
x = (int)(vx[i] * s);
y = (int)(vy[i] * s - gravity * s * s);
g.drawLine(ox + x, oy - y, ox + x, oy - y);
}
}
}
++t;
} else
sleep = true;
}
}
}